package no.ntnu.item.arctis.runtime;

import java.util.Hashtable;

/**
 * This class provides access to the functions provided by the runtime added during the
 * compilation process. 
 * 
 * Note that class <code>Block</code> or any subclasses of it provide the same functionality in a
 * more comfortable way. We therefore recommend that any building block should extend class <code>Block</code> 
 * or any of its subclasses instead of accessing <code>AbstractRuntime</code> directly.
 * 
 * @author kraemer
 *
 */
public abstract class AbstractRuntime {
	
	//protected static final Hashtable instances = new Hashtable();
	
	private static AbstractRuntime instance;
	
	public abstract boolean isSessionActive(String sessionID);

	/**
	 * 
	 * @param blockID the blockID obtained via <code>IArctisBuildingBlock</cock>
	 * @return the instance of the runtime handling this block
	 */
	public static AbstractRuntime getRuntime() {
		return instance;
	}
	
	/**
	 * @deprecated
	 * @param blockID
	 * @return
	 */
	public static AbstractRuntime getRuntime(String blockID) {
		return instance;
	}
	
	public static void setRuntime(AbstractRuntime runtime) {
		instance = runtime;
	}
	
	protected static final Hashtable context = new Hashtable();
    
	/**
	 * @deprecated use the setProperty() method of Block.
	 * @param id
	 * @param contextObject
	 */
    public void addContext(String id, Object contextObject) {
    	if(id==null) {
    		System.err.println("Key cannot be null for adding a context object");
    		return;
    	}
    	if(contextObject==null) {
    		System.err.println("Tried to add context object with value null for key " + id);
    		return;
    	}
        AbstractRuntime.context.put(id, contextObject);
    }

    /**
	 * @deprecated use the getProperty() method of Block.
	 */
    public Object getContext(String id) {
        return AbstractRuntime.context.get(id);
    }
    
    public abstract boolean isRunning();

		
	/**
	 * Sends a signal into the runtime system. This signal must be 
	 * received by the UML model of the same building block. 
	 * The provided signal ID must match that of the UML signal.
	 * The provided data type must match the one declared for the UML signal.
	 * 
	 * (see <a href="http://arctis.item.ntnu.no/doc/reacting_on_external_events"></a>)
     *
	 * 
	 * @param blockID - the block ID provided via <code>IArctisBuildingBlock</cock>.
	 * @param signalName - the name of the signal.
	 * @param data - data to be transported by the signal. 
	 */
	public abstract void sendToBlock(String sessionID, String blockID, String signalName, Object data);

	/**
	 * Sends a signal into the runtime system. This signal must be 
	 * received by the UML model of the same building block. 
	 * The provided signal ID must match that of the UML signal.
	 * 
	 * (see <a href="http://arctis.item.ntnu.no/doc/reacting_on_external_events"></a>)
	 * 
	 * @param blockID - the block ID provided via <code>IArctisBuildingBlock</cock>.
	 * @param signalName - the name of the signal.  
	 */
	public abstract void sendToBlock(String sessionID, String blockID, String signalName);


	/**
	 * Building blocks may report exception via this method. The runtime support system
	 * will notify the user.
	 * Note that instead of using this method, applications should take care of exceptions themselves
	 * and take proper actions. This method should only be used for preliminary systems during early tests.
	 * @param explanation - an explanation of the situation
	 * @param t - the throwable, if available
	 */
    public abstract void catchApplicationException(String explanation, Throwable t);

}